﻿using MiniFox.Components;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MiniFox.Data
{
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public abstract class DataCommand<TEntity> : Component, IDataCommand<TEntity> where TEntity : class
    {
        /// <summary>
        /// 
        /// </summary>
        int _timeOut;
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<CommandErrorEventArgs> OnError;
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<CommandEventArgs> CommandExecuted;
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<CommandEventArgs> CommandCreated;

        /// <summary>
        /// 
        /// </summary>
        public DataCommand()
        {
            _timeOut = 30;

        }
        /// <summary>
        /// 查询命令执行超时时长，默认30秒(单位：秒)
        /// </summary>
        public int TimeOut
        {
            get { return _timeOut; }
            set { _timeOut = value; }
        }
        /// <summary>
        /// 
        /// </summary>
        public abstract string ConnectionString
        {
            get;
        }

        #region 提供事件观察接口

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlText"></param>
        /// <param name="parameters"></param>
        protected virtual void OnCreated(string sqlText, IDictionary<string, object> parameters)
        {
            CommandCreated?.Invoke(this, new CommandEventArgs
            {
                ConnectionString = this.ConnectionString,
                CommandText = sqlText,
                Parameters = parameters
            });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlText"></param>
        /// <param name="parameters"></param>
        protected virtual void OnExecuted(string sqlText, IDictionary<string, object> parameters)
        {
            CommandExecuted?.Invoke(this, new CommandEventArgs
            {
                ConnectionString = this.ConnectionString,
                CommandText = sqlText,
                Parameters = parameters
            });
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlText"></param>
        /// <param name="parameters"></param>
        /// <param name="exception"></param>
        protected virtual void OnErrorHandled(string sqlText, IDictionary<string, object> parameters, Exception exception)
        {
            var e = new CommandErrorEventArgs
            {
                ConnectionString = this.ConnectionString,
                CommandText = sqlText,
                Parameters = parameters,
                Error = exception
            };
            this.WriteErrorLog(e.Error.Message, e.Error);
            OnError?.Invoke(this, e);

            if (e.HandleError)
                throw e.Error;
        }

        #endregion
    }
}
